package redis

import (
	"github.com/xiaobaiskill/fang/pkg/models"
	"strconv"
	"strings"
	"fmt"
	"time"
	"math/rand"
)
var RedisConn *RedisDB

type RedisDB struct {
	conn *Conn
	ipsKey string
	ipPrefixKey string
}

func NewRedisDB(conn *Conn) *RedisDB  {
	return &RedisDB{
		conn:conn,
		ipsKey: "ips",
		ipPrefixKey: "ip:",
	}
}

func (r *RedisDB) InsertIP(ip *models.IP) error {
	err := r.conn.Hmset(r.ipPrefixKey + ip.Data,"type1",ip.Type1,"type2",ip.Type2,"speed",fmt.Sprintf("%d",ip.Speed))
	if err!=nil {
		return err
	}
	err = r.conn.ZAdd(r.ipsKey,float64(ip.Speed),ip.Data)
	if err!=nil {
		return err
	}
	return nil
}

func (r *RedisDB) CountIP() (int64, error) {
	return r.conn.ZCard(r.ipsKey)
}

func (r *RedisDB) DeleteIP(ip *models.IP) error  {
	err := r.conn.Del(r.ipPrefixKey + ip.Data)
	if err!=nil {
		return err
	}
	_,err = r.conn.ZRem(r.ipsKey,ip.Data)
	if err!=nil {
		return err
	}
	return nil
}

func (r *RedisDB) GetOneIP(ip string) (*models.IP, error)   {
	fields,err := r.conn.Hgetall(r.ipPrefixKey+ip)
	if err!=nil {
		return nil,err
	}
	ipModel := models.NewIP()
	ipModel.Data = ip
	if fields!=nil && len(fields)>0 {
		for i:=0;i< len(fields);i++ {
			field := fields[i]
			switch field.Field {
			case "type1":
				ipModel.Type1 = field.Value
				break
			case "type2":
				ipModel.Type2 = field.Value
				break
			case "speed":
				ipModel.Speed,_ = strconv.ParseInt(field.Value,10,64)
				break


			}
		}
	}
	return ipModel,nil
}

func (r *RedisDB) GetAllIP() ([]*models.IP, error) {
	fieldValues,err := r.conn.ZRange(r.ipsKey,0,-1)
	if err!=nil {
		return nil,err
	}
	ipModels := make([]*models.IP,0)
	if len(fieldValues)>0 {
		for i:=0;i< len(fieldValues);i=i+2 {
			ipModel,err := r.GetOneIP(fieldValues[i])
			if err!=nil {
				continue
			}
			ipModels = append(ipModels,ipModel)
		}
	}
	return ipModels,nil
}

func (r *RedisDB) GetNumIPWithType(num int)([]*models.IP,error){
	fieldValues,err := r.conn.ZRange(r.ipsKey,0,int64(num))
	if err!=nil {
		return nil,err
	}
	ipModels := make([]*models.IP,0)
	if len(fieldValues) >0{
		for _,v := range fieldValues{
			ipModel,err := r.GetOneIP(v)
			if err!=nil {
				continue
			}
			ipModels = append(ipModels,ipModel)
		}
	}
	return ipModels,nil
}

// 随机获取 数据
func (r *RedisDB) GetRandNumIPWithType(num int)([]*models.IP,error){
	count,err := r.conn.ZCard(r.ipsKey)  // 获取成员数
	if err != nil {
		return nil,err
	}

	// 总数 大于 需要数
	if int(count) > num {
		rand.Seed(time.Now().UnixNano())
		startNum := int64(rand.Intn(int(count)-num))
		fieldValues,err := r.conn.ZRange(r.ipsKey,startNum,startNum + int64(num))
		if err!=nil {
			return nil,err
		}
		ipModels := make([]*models.IP,0)
		if len(fieldValues) >0{
			for _,v := range fieldValues{
				ipModel,err := r.GetOneIP(v)
				if err!=nil {
					continue
				}
				ipModels = append(ipModels,ipModel)
			}
		}
		return ipModels,nil
	}

	// 总数小于需要数
	return r.GetNumIPWithType(num)
}


func (r *RedisDB) FindIPWithType(typ string) ([]*models.IP, error) {
	ips,err := r.GetAllIP()
	if err!=nil {
		return nil,err
	}
	resultIps := make([]*models.IP,0)
	if len(ips)>0 {
		for _,ip :=range ips {
			if strings.ToLower(typ) == "http" && strings.ToLower(ip.Type1) !="http" {
				continue
			}
			if strings.ToLower(typ) == "https" && strings.ToLower(ip.Type2) !="https" {
				continue
			}
			resultIps = append(resultIps,ip)
		}
	}
	return resultIps,nil
}

func (r *RedisDB) ExistHttps() (bool,error) {
	ips,err := r.FindIPWithType("https")
	if err!=nil {
		return false,err
	}
	return len(ips)>0,nil
}
